home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / agrep / sgrep.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  18KB  |  685 lines

  1. /* Copyright (c) 1991 Sun Wu and Udi Manber.  All Rights Reserved. */
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #define MAXSYM  256
  5. #define MAXMEMBER 8192
  6. #define    CHARTYPE    unsigned char
  7. #define MaxError 20
  8. #define MAXPATT 256
  9. #define MAXLINE 1024
  10. #define MaxCan  2048
  11. #define BLOCKSIZE    8192
  12. #define MAX_SHIFT_2  4096
  13. #define ON      1
  14. #define LOG_ASCII 8
  15. #define LOG_DNA  3
  16. #define MAXMEMBER_1 65536
  17. #define LONG_EXAC  20
  18. #define LONG_APPX  24
  19. #define W_DELIM    128
  20.  
  21. extern COUNT, FNAME, SILENT, FILENAMEONLY, num_of_matched;
  22. extern DNA ;  /* DNA flag is set in checksg when pattern is DNA pattern and
  23.          p_size > 16  */
  24. extern WORDBOUND, WHOLELINE, NOUPPER;
  25. extern unsigned char CurrentFileName[],  Progname[]; 
  26. extern unsigned Mask[];
  27. extern unsigned endposition;
  28.  
  29. unsigned char BSize;                /* log_c m   */
  30. unsigned char char_map[MAXSYM];
  31.     
  32.  
  33. /* data area */
  34. int shift_1;
  35. CHARTYPE SHIFT[MAXSYM];
  36. CHARTYPE MEMBER[MAXMEMBER];
  37. CHARTYPE pat[MAXPATT];
  38. unsigned Hashmask;
  39. char MEMBER_1[MAXMEMBER_1];
  40. CHARTYPE TR[MAXSYM];
  41.  
  42. char_tr(pat, m)
  43.     unsigned char *pat;
  44.     int *m;
  45. {
  46. int i;
  47. unsigned char temp[MAXPATT];
  48.     for(i=0; i<MAXSYM; i++) TR[i] = i;
  49.     if(NOUPPER) {
  50.         for(i='A'; i<= 'Z'; i++) TR[i] = i + 'a' - 'A';
  51.     }
  52.     if(WORDBOUND) { /* SUN: To be added to be more complete */
  53.         for(i=0; i<128; i++) {
  54.             if(!isalnum(i)) TR[i] = W_DELIM;
  55.         }
  56.     }
  57.     if(WHOLELINE) {
  58.         memcpy(temp, pat, *m);
  59.         pat[0] = '\n';
  60.         memcpy(pat+1, temp, *m);
  61.         pat[*m+1] = '\n';
  62.         pat[*m+2] = 0;
  63.         *m = *m + 2;
  64.     }
  65. }
  66.  
  67. sgrep(pat, m, fd, D)
  68. CHARTYPE *pat;  int fd, m, D;
  69.     CHARTYPE text[BLOCKSIZE+2*MAXLINE+MAXPATT]; /* input text stream */
  70.     int offset = 2*MAXLINE;
  71.     int buf_end, num_read, i, start, end, residue = 0;
  72.     if(pat[0] == '^' || pat[0] == '$') pat[0] = '\n';
  73.     if(pat[m-1] == '^' || pat[m-1] == '$') pat[m-1] = '\n';
  74.     char_tr(pat, &m);   /* will change pat, and m if WHOLELINE is ON */
  75.     text[offset-1] = '\n';  /* initial case */
  76.     for(i=0; i < MAXLINE; i++) text[i] = 0;   /* security zone */
  77.     start = offset;   
  78.     if(WHOLELINE) start--;
  79.     if(m >= MAXPATT) {
  80.          fprintf(stderr, "%s: pattern too long\n", Progname);
  81.          exit(2);
  82.     }
  83.     if(D == 0) {
  84.     if(m > LONG_EXAC) m_preprocess(pat);
  85.     else prep_bm(pat, m);
  86.     }
  87.     else if (DNA) prep4(pat, m);
  88.      else     if(m >= LONG_APPX) am_preprocess(pat);
  89.         else {
  90.             prep(pat, m, D);
  91.             initmask(pat, Mask, m, 0, &endposition); 
  92.         }
  93.     for(i=1; i<=m; i++) text[BLOCKSIZE+offset+i] = pat[m-1];
  94.         /* to make sure the skip loop in bm() won't go out of bound */
  95.     while( (num_read = read(fd, text+offset, BLOCKSIZE)) > 0) 
  96.     {
  97.        buf_end = end = offset + num_read -1 ;
  98.        while(text[end]  != '\n' && end > offset) end--;
  99.        residue = buf_end - end + 1 ;
  100.        text[start-1] = '\n';
  101.        if(D==0)  {
  102.         if(m > LONG_EXAC) monkey(pat, m, text+start, text+end);
  103.         else bm(pat, m, text+start, text+end);
  104.        }
  105.        else {
  106.         if(DNA) monkey4( pat, m, text+start, text+end, D  );
  107.         else {
  108.           if(m >= LONG_APPX) a_monkey(pat, m, text+start, text+end, D);
  109.           else       agrep(pat, m, text+start, text+end, D);
  110.         }
  111.        }
  112.        if(FILENAMEONLY && num_of_matched) {
  113.             printf("%s\n", CurrentFileName);
  114.             return; }
  115.        start = offset - residue ;
  116.        if(start < MAXLINE) {
  117.             start = MAXLINE; 
  118.        }
  119.        strncpy(text+start, text+end, residue);
  120.        start++;
  121.     } /* end of while(num_read = ... */
  122.     return;
  123. } /* end sgrep */
  124.  
  125. /* SUN: bm assumes that the content of text[n]...text[n+m-1] is 
  126. pat[m-1] such that the skip loop is guaranteed to terminated */
  127.  
  128. bm(pat, m, text, textend)
  129.     CHARTYPE *text, *textend, *pat;  int m;
  130. {
  131. register int shift;
  132. register int  m1, j, d1; 
  133.  
  134. /*
  135. printf("%d\t", textend - text);
  136. printf("%c, %c", *text, *textend);
  137. */
  138.  
  139. d1 = shift_1;    /* at least 1 */
  140. m1 = m - 1;
  141. shift = 0;       
  142. while (text <= textend) {
  143.     shift = SHIFT[*(text += shift)];
  144.     while(shift) {          
  145.         shift = SHIFT[*(text += shift)];
  146.         shift = SHIFT[*(text += shift)];
  147.         shift = SHIFT[*(text += shift)];
  148.     }
  149.         j = 0;
  150.         while(TR[pat[m1 - j]] == TR[*(text - j)]) {
  151.             if(++j == m)  break;       /* if statement can be
  152.                             saved, but for safty ... */
  153.         }
  154.             if (j == m ) { 
  155.             if(text > textend) return;
  156.             if(WORDBOUND) {
  157.                 if(TR[*(text+1)] != W_DELIM) goto CONT;
  158.                 if(TR[*(text-m)] != W_DELIM) goto CONT;
  159.             }
  160.             num_of_matched++;
  161.             if(FILENAMEONLY) return;
  162.             if(!(COUNT)) {
  163.                 if(FNAME) printf("%s: ", CurrentFileName);
  164.                 while(*(--text) != '\n');
  165.                 while(*(++text) != '\n') putchar(*(text));
  166.                 putchar(*text);
  167.             }
  168.             else { while(*text != '\n') text++; } 
  169. CONT:
  170.             shift = 1;
  171.                 }
  172.         else shift = d1;
  173.   }
  174. return;
  175. }
  176.  
  177.   
  178. /* initmask() initializes the mask table for the pattern                    */ 
  179. /* endposition is a mask for the endposition of the pattern                 */
  180. /* endposition will contain k mask bits if the pattern contains k fragments */
  181. initmask(pattern, Mask, m, D, endposition)
  182. CHARTYPE *pattern; unsigned *Mask; register int m, D; unsigned *endposition;
  183. {
  184.   register unsigned Bit1, c;
  185.   register int i, j, frag_num;
  186.  
  187.   Bit1 = 1 << 31;    /* the first bit of Bit1 is 1, others 0.  */
  188.   frag_num = D+1; *endposition = 0;
  189.   for (i = 0; i < frag_num; i++) *endposition = *endposition | (Bit1 >> i);
  190.   *endposition = *endposition >> (m - frag_num);
  191.   for(i = 0; i < m; i++) 
  192.           if (pattern[i] == '^' || pattern[i] == '$') {
  193.               pattern[i] = '\n'; 
  194.           }
  195.   for(i = 0; i < MAXSYM; i++) Mask[i] = ~0;
  196.   for(i = 0; i < m; i++)     /* initialize the mask table */
  197.   {  c = pattern[i];
  198.      for ( j = 0; j < m; j++)
  199.            if( c == pattern[j] )
  200.                Mask[c] = Mask[c] & ~( Bit1 >> j ) ;
  201.   }
  202. }
  203.  
  204. prep(Pattern, M, D)             /* preprocessing for partitioning_bm */
  205.     CHARTYPE *Pattern;  /* can be fine-tuned to choose a better partition */
  206.     register int M, D;
  207. {
  208. register int i, j, k, p, shift;
  209. register unsigned m;
  210. unsigned hash, b_size = 3;
  211.     m = M/(D+1);
  212.     p = M - m*(D+1);
  213.     for (i = 0; i < MAXSYM; i++) SHIFT[i] = m;
  214.     for (i = M-1; i>=p ; i--) {
  215.         shift = (M-1-i)%m;
  216.         hash = Pattern[i];
  217.         if(SHIFT[hash] > shift) SHIFT[hash] = shift;
  218.     }
  219. #ifdef DEBUG
  220.     for(i=0; i<M; i++) printf(" %d,", SHIFT[Pattern[i]]);
  221.     printf("\n");
  222. #endif
  223.     shift_1 = m;
  224.     for(i=0; i<D+1; i++) {
  225.         j = M-1 - m*i;
  226.         for(k=1; k<m; k++) {
  227.             for(p=0; p<D+1; p++) 
  228.                 if(Pattern[j-k] == Pattern[M-1-m*p]) 
  229.                     if(k < shift_1) shift_1 = k;
  230.         }
  231.     }
  232. #ifdef DEBUG
  233.     printf("\nshift_1 = %d", shift_1);
  234. #endif
  235.     if(shift_1 == 0) shift_1 = 1;
  236.     for(i=0; i<MAXMEMBER; i++) MEMBER[i] = 0;
  237.     if (m < 3) b_size = m;
  238.     for(i=0; i<D+1; i++) {
  239.         j = M-1 - m*i;
  240.         hash = 0;
  241.         for(k=0; k<b_size; k++) {
  242.             hash = (hash << 2) + Pattern[j-k];
  243.         }
  244. #ifdef DEBUG
  245.     printf(" hash = %d,", hash);
  246. #endif
  247.         MEMBER[hash] = 1;
  248.     }
  249. }
  250.  
  251.  
  252. agrep( pat, M, text, textend, D ) 
  253. int M, D ; register CHARTYPE *text, *textend, *pat;
  254. {
  255.   register int i;
  256.   register int m = M/(D+1);
  257.   register CHARTYPE *textstart;
  258.   register int shift, HASH;
  259.   int  j=0, k, m1, d1;
  260.   int  n, cdx;
  261.   int  Candidate[MaxCan][2], round, lastend=0;
  262.   unsigned R1[MaxError+1], R2[MaxError+1]; 
  263.   register unsigned int r1, endpos, c; 
  264.   unsigned currentpos;
  265.   unsigned Bit1;
  266.   unsigned r_newline;
  267.  
  268.   Candidate[0][0] = Candidate[0][1] = 0; 
  269.   d1 = shift_1;
  270.   cdx = 0;
  271.   if(m < 3) r1 = m;
  272.   else r1 = 3;
  273.   textstart = text;
  274.   shift = m-1;
  275.   while (text < textend) {
  276.     shift = SHIFT[*(text += shift)];
  277.     while(shift) {
  278.         shift = SHIFT[*(text += shift)];
  279.         shift = SHIFT[*(text += shift)];
  280.     }
  281.         j = 1; HASH = *text;
  282.         while(j < r1) { HASH = (HASH << 2) + *(text-j);
  283.                 j++; }
  284.             if (MEMBER[HASH]) { 
  285.             i = text - textstart;
  286.                          if((i - M - D - 10) > Candidate[cdx][1]) {     
  287.                 Candidate[++cdx][0] = i-M-D-2;
  288.                               Candidate[cdx][1] = i+M+D; }
  289.                          else Candidate[cdx][1] = i+M+D;
  290.             shift = d1;
  291.                 }
  292.         else shift = d1;
  293.   }
  294.  
  295.  
  296.   text = textstart;
  297.   n = textend - textstart;
  298.   r_newline = '\n';
  299.   /* for those candidate areas, find the D-error matches                     */
  300.   if(Candidate[1][0] < 0) Candidate[1][0] = 0;
  301.   endpos = endposition;                /* the mask table and the endposition */
  302.   Bit1 = (1 << 31);
  303.   for(round = 0; round <= cdx; round++)
  304.   {  i = Candidate[round][0] ; 
  305.      if(Candidate[round][1] > n) Candidate[round][1] = n;
  306.      if(i < 0) i = 0;
  307. #ifdef DEBUG
  308.      printf("round: %d, start=%d, end=%d, ", round, i, Candidate[round][1]);
  309. #endif
  310.      R1[0] = R2[0] = ~0;
  311.      R1[1] = R2[1] = ~Bit1;
  312.      for(k = 1; k <= D; k++) R1[k] = R2[k] = (R1[k-1] >> 1) & R1[k-1];
  313.      while (i < Candidate[round][1])                     
  314.      {  
  315.         c = text[i++];
  316.             if(c == r_newline) {
  317.                for(k = 0 ; k <= D; k++) R1[k] = R2[k] = (~0 );
  318.             }
  319.             r1 = Mask[c];
  320.             R1[0] = (R2[0] >> 1) | r1;
  321.             for(k=1; k<=D; k++)
  322.                 R1[k] = ((R2[k] >> 1) | r1) & R2[k-1] & ((R1[k-1] & R2[k-1]) >> 1);
  323.             if((R1[D] & endpos) == 0) { 
  324.                                     num_of_matched++;
  325.                                     if(FILENAMEONLY) { return; }
  326.                                     currentpos = i;
  327.                                     if(i <= lastend) i = lastend;
  328.                                     else {
  329.                                        s_output(text, ¤tpos); 
  330.                                        i = currentpos; 
  331.                                     }
  332.                                     lastend = i;
  333.                                     for(k=0; k<=D; k++) R1[k] = R2[k] = ~0;
  334.                                   }
  335.             c = text[i++];
  336.             if(c == r_newline) {
  337.                 for(k = 0 ; k <= D; k++) R1[k] = R2[k] = (~0 );
  338.             }
  339.             r1 = Mask[c];
  340.             R2[0] = (R1[0] >> 1) | r1;
  341.             for(k = 1; k <= D; k++)
  342.                 R2[k] = ((R1[k] >> 1) | r1) & R1[k-1] & ((R1[k-1] & R2[k-1]) >> 1);
  343.             if((R2[D] & endpos) == 0) { currentpos = i;
  344.                                     num_of_matched++;
  345.                                     if(FILENAMEONLY) { return; }
  346.                                     if(i <= lastend) i = lastend;
  347.                                     else {
  348.                                        s_output(text, ¤tpos); 
  349.                                        i = currentpos; 
  350.                                     }
  351.                                     lastend = i;
  352.                                     for(k=0; k<=D; k++) R1[k] = R2[k] = ~0;
  353.                                   }
  354.      }
  355.   }
  356.   return;
  357. }
  358.  
  359. s_output (text, i) 
  360. int *i; CHARTYPE *text;
  361. {
  362. int kk, bp;
  363.         if(SILENT) return;
  364.         if(COUNT) {
  365.         while(text[*i] != '\n') *i = *i + 1; 
  366.         return;
  367.     }
  368.         if(FNAME == ON) printf("%s: ", CurrentFileName);
  369.         bp = *i;
  370.         while(text[--bp] != '\n');
  371.         while(text[++bp] != '\n') putchar(text[bp]);
  372.         putchar('\n');
  373.         *i = bp;
  374. }
  375.  
  376.  
  377. prep_bm(Pattern, m)      
  378.     unsigned char *Pattern;
  379.     register m;
  380. {
  381. int i, j;
  382. unsigned hash;
  383. unsigned char lastc;
  384.     for (i = 0; i < MAXSYM; i++) SHIFT[i] = m;
  385.     for (i = m-1; i>=0; i--) {
  386.         hash = TR[Pattern[i]];
  387.         if(SHIFT[hash] >= m - 1) SHIFT[hash] = m-1-i;
  388.     }
  389.     shift_1 = m-1;
  390.     lastc = TR[Pattern[m-1]];
  391.     for (i= m-2; i>=0; i--) {
  392.         if(TR[Pattern[i]] == lastc )
  393.             { shift_1 = m-1 - i;  i = -1; }
  394.     }
  395.     if(shift_1 == 0) shift_1 = 1;
  396.     if(NOUPPER) for(i='A'; i<='Z'; i++) SHIFT[i] = SHIFT[i +  'a' - 'A'];
  397. #ifdef DEBUG
  398.     for(i='a'; i<='z'; i++) printf("%c: %d", i, SHIFT[i]); printf("\n");
  399.     for(i='A'; i<='Z'; i++) printf("%c: %d", i, SHIFT[i]); printf("\n");
  400. #endif
  401. }
  402.  
  403.  
  404. /* a_monkey() the approximate monkey move */
  405.  
  406. a_monkey( pat, m, text, textend, D ) 
  407. register int m, D ; register CHARTYPE *text, *textend, *pat;
  408. {
  409. register CHARTYPE *oldtext;
  410. register unsigned hash, i, hashmask, suffix_error; 
  411. register int  m1 = m-1-D, j, pos; 
  412.  
  413.       hashmask = Hashmask;
  414.       oldtext  = text;
  415.       while (text < textend) {
  416.              text = text+m1;
  417.              suffix_error = 0;
  418.              while(suffix_error <= D) {
  419.             hash = *text--;
  420.             while(MEMBER_1[hash]) {
  421.                       hash = ((hash << LOG_ASCII) + *(text--)) & hashmask;
  422.             }
  423.             suffix_error++;
  424.              }
  425.              if(text <= oldtext) {
  426.                    if((pos = verify(m, 2*m+D, D, pat, oldtext)) > 0)  {
  427.                 text = oldtext+pos;
  428.                 if(text > textend) return;
  429.                 num_of_matched++;
  430.                 if(FILENAMEONLY) return;
  431.                 if(!(COUNT)) {
  432.                     if(FNAME) printf("%s: ", CurrentFileName);
  433.                     while(*(--text) != '\n');
  434.                      while(*(++text) != '\n') putchar(*text);
  435.                         printf("\n");
  436.                 }
  437.                 else {
  438.                     while(*text != '\n') text++;
  439.                 }
  440.                }
  441.                else { 
  442.                     text = oldtext + m;
  443.                }
  444.              }
  445.              oldtext = text; 
  446.       }
  447. }
  448.  
  449. /* monkey uses two characters for delta_1 shifting */
  450.  
  451. CHARTYPE SHIFT_2[MAX_SHIFT_2];
  452.  
  453. monkey( pat, m, text, textend  ) 
  454. register int m  ; register CHARTYPE *text, *textend, *pat;
  455. {
  456. register unsigned hash, i; 
  457. register CHARTYPE shift;
  458. register int  m1, j; 
  459. register unsigned r_newline;
  460.  
  461. r_newline = '\n';
  462.  
  463.   m1 = m - 1;
  464.   text = text+m1;
  465.   while (text < textend) {
  466.     hash = *text;
  467.     hash = (hash << 3) + *(text-1);
  468.     shift = SHIFT_2[hash];
  469.     while(shift) {
  470.         text = text + shift;
  471.         hash = (*text << 3) + *(text-1);
  472.         shift = SHIFT_2[hash];
  473.     }
  474.     j = 0;
  475.     while(TR[pat[m1 - j]] == TR[*(text - j)]) { if(++j == m) break; }
  476.     if (j == m ) { 
  477.         if(text >= textend) return;
  478.                 num_of_matched++;
  479.                 if(FILENAMEONLY)  return;
  480.             if(COUNT) {
  481.               while (*text != r_newline) text++;
  482.               text--;
  483.         }
  484.         else {
  485.               if(FNAME) printf("%s: ", CurrentFileName);
  486.                           while(*(--text) != r_newline);
  487.                           while(*(++text) != r_newline) putchar(*text);
  488.               printf("\n");
  489.               text--;
  490.         }
  491.         }
  492.     text++;
  493.   }
  494. }
  495.  
  496. am_preprocess(Pattern)
  497. CHARTYPE *Pattern;
  498. {
  499. int i, j, m;
  500. unsigned hash;
  501.     m = strlen(Pattern);
  502.     for (i = 1, Hashmask = 1 ; i<16 ; i++) Hashmask = (Hashmask << 1) + 1 ;
  503.     for (i = 0; i < MAXMEMBER_1; i++) MEMBER_1[i] = 0;
  504.     for (i = m-1; i>=0; i--) {
  505.         MEMBER_1[Pattern[i]] = 1;
  506.         }
  507.     for (i = m-1; i > 0; i--) {
  508.            MEMBER_1[(Pattern[i] << LOG_ASCII) + Pattern[i-1]] = 1;
  509.     }
  510. }
  511.  
  512.  
  513. verify(m, n, D, pat, text)
  514. register int m, n, D;
  515. CHARTYPE *pat, *text;
  516. {   
  517.     int A[MAXPATT], B[MAXPATT];
  518.     register int last = D;      
  519.     register int cost = 0;  
  520.     register int k, i, c;
  521.     register int m1 = m+1;
  522.     CHARTYPE *textend = text+n;
  523.     CHARTYPE *textbegin = text;
  524.  
  525.    for (i = 0; i <= m1; i++)  A[i] = B[i] = i;
  526.    while (text < textend)
  527.    {
  528.        for (k = 1; k <= last; k++)
  529.        {
  530.            cost = B[k-1]+1; 
  531.            if (pat[k-1] != *text)
  532.            {   if (B[k]+1 < cost) cost = B[k]+1; 
  533.                if (A[k-1]+1 < cost) cost = A[k-1]+1; }
  534.            else cost = cost -1; 
  535.            A[k] = cost; 
  536.        }
  537.        if(pat[last] == *text++) { A[last+1] = B[last]; last++; }
  538.        if(A[last] < D) A[last+1] = A[last++]+1;
  539.        while (A[last] > D) last = last - 1;
  540.        if(last >= m) return(text - textbegin - 1);
  541.        if(*text == '\n') {
  542.             last = D;
  543.         for(c = 0; c<=m1; c++) A[c] = B[c] = c;
  544.        }
  545.        for (k = 1; k <= last; k++)
  546.        {
  547.            cost = A[k-1]+1; 
  548.            if (pat[k-1] != *text)
  549.            {   if (A[k]+1 < cost) cost = A[k]+1; 
  550.                if (B[k-1]+1 < cost) cost = B[k-1]+1; }
  551.            else cost = cost -1; 
  552.            B[k] = cost;
  553.        }
  554.        if(pat[last] == *text++) { B[last+1] = A[last]; last++; }
  555.        if(B[last] < D) B[last+1] = B[last++]+1;
  556.        while (B[last] > D) last = last -1;
  557.        if(last >= m)   return(text - textbegin - 1);
  558.        if(*text == '\n') {
  559.             last = D;
  560.         for(c = 0; c<=m1; c++) A[c] = B[c] = c;
  561.        }
  562.    }    
  563.    return(0);
  564. }
  565.  
  566. /* preprocessing for monkey()   */
  567.  
  568. m_preprocess(Pattern)
  569. CHARTYPE *Pattern;
  570. {
  571. int i, j, m;
  572. unsigned hash;
  573.     m = strlen(Pattern);
  574.     for (i = 0; i < MAX_SHIFT_2; i++) SHIFT_2[i] = m;
  575.     for (i = m-1; i>=1; i--) {
  576.         hash = Pattern[i];
  577.         hash = hash << 3;
  578.         for (j = 0; j< MAXSYM; j++) {
  579.             if(SHIFT_2[hash+j] == m) SHIFT_2[hash+j] = m-1;
  580.         }
  581.         hash = hash + Pattern[i-1];
  582.         if(SHIFT_2[hash] >= m - 1) SHIFT_2[hash] = m-1-i;
  583.     }
  584.     shift_1 = m-1;
  585.     for (i= m-2; i>=0; i--) {
  586.         if(Pattern[i] == Pattern[m-1] )
  587.             { shift_1 = m-1 - i;  i = -1; }
  588.     }
  589.     if(shift_1 == 0) shift_1 = 1;
  590.     SHIFT_2[0] = 0;
  591. }
  592.  
  593. /* monkey4() the approximate monkey move */
  594.  
  595. char *MEMBER_D;
  596.  
  597. monkey4( pat, m, text, textend, D  ) 
  598. register int m, D ; register unsigned char *text, *pat, *textend;
  599. {
  600. register unsigned char *oldtext;
  601. register unsigned hash, i, hashmask, suffix_error; 
  602. register int m1=m-1-D, j, pos; 
  603.  
  604.   hashmask = Hashmask;
  605.   oldtext = text ;
  606.   while (text < textend) {
  607.      text = text + m1;
  608.      suffix_error = 0;
  609.      while(suffix_error <= D) {
  610.     hash = char_map[*text--];
  611.     hash = ((hash << LOG_DNA) + char_map[*(text--)]) & hashmask;
  612.     while(MEMBER_D[hash]) {
  613.           hash = ((hash << LOG_DNA) + char_map[*(text--)]) & hashmask;
  614.     }
  615.     suffix_error++;
  616.      }
  617.      if(text <= oldtext) {
  618.                    if((pos = verify(m, 2*m+D, D, pat, oldtext)) > 0)  {
  619.                 text = oldtext+pos;
  620.                 if(text > textend) return;
  621.                 num_of_matched++;
  622.                 if(FILENAMEONLY) return;
  623.                 if(!(COUNT)) {
  624.                     if(FNAME) printf("%s:", CurrentFileName);
  625.                     while(*(--text) != '\n');
  626.                      while(*(++text) != '\n') putchar(*text);
  627.                         printf("\n");
  628.                     text++;
  629.                 }
  630.                 else {
  631.                     while(*text != '\n') text++;
  632.                     text++;
  633.                 }
  634.                }
  635.                else text = oldtext + m;
  636.      }
  637.      oldtext = text; 
  638.   }
  639. }
  640.  
  641. prep4(Pattern, m)
  642. char *Pattern; int m;
  643. {
  644. int i, j, k;
  645. unsigned hash;
  646.  
  647. for(i=0; i< MAXSYM; i++) char_map[i] = 0;
  648. char_map['a'] = char_map['A'] = 4;
  649. char_map['g'] = char_map['g'] = 1;
  650. char_map['t'] = char_map['t'] = 2;
  651. char_map['c'] = char_map['c'] = 3;
  652. char_map['n'] = char_map['n'] = 5;
  653.  
  654.     BSize = blog(4, m);
  655.     for (i = 1, Hashmask = 1 ; i<BSize*LOG_DNA; i++) Hashmask = (Hashmask << 1) + 1 ;
  656.     MEMBER_D = (char *) malloc((Hashmask+1)  * sizeof(char));
  657. #ifdef DEBUG
  658.     printf("BSize = %d", BSize);
  659. #endif 
  660.     for (i=0; i <= Hashmask; i++) MEMBER_D[i] = 0;
  661.     for (j=0; j < BSize; j++) {
  662.             for(i=m-1; i >= j; i--) {
  663.                hash = 0;
  664.            for(k=0; k <= j; k++) 
  665.           hash = (hash << LOG_DNA) +char_map[Pattern[i-k]]; 
  666. #ifdef DEBUG
  667.            printf("< %d >, ", hash);
  668. #endif
  669.            MEMBER_D[hash] = 1;
  670.             }
  671.         }
  672. }
  673.  
  674. blog(base, m )
  675. int base, m;
  676. {
  677. int i, exp;
  678.     exp = base;
  679.         m = m + m/2;
  680.     for (i = 1; exp < m; i++) exp = exp * base;
  681.     return(i);
  682. }
  683.  
  684.